package com.xci.core.helper;

import cn.afterturn.easypoi.excel.annotation.Excel;
import cn.afterturn.easypoi.excel.annotation.ExcelTarget;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.excel.entity.params.ExcelBaseEntity;
import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity;
import cn.afterturn.easypoi.excel.export.ExcelExportService;
import cn.afterturn.easypoi.exception.excel.ExcelExportException;
import cn.afterturn.easypoi.exception.excel.enums.ExcelExportEnum;
import cn.afterturn.easypoi.util.PoiPublicUtil;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Excel操作帮助类
 * @author 吕艳阳
 */
public class ExcelHelper {

    /**
     * Web导出Excel
     * @param data 导出的数据
     * @param pojoClass 实体对象类型
     * @param title 标题
     */
    public static void exportWeb(@NotNull List data, Class<?> pojoClass, String title) {
        HttpServletResponse response = WebHelper.getResponse();
        if(response != null) {
            exportWeb(response, data, pojoClass, title, null, null);
        }
    }

    /**
     * Web导出Excel
     * @param data 导出的数据
     * @param pojoClass 实体对象类型
     * @param title 标题
     * @param fieldNames 导出字段名称字符串,逗号隔开(@Excel注解中的name属性)
     */
    public static void exportWeb(@NotNull List data, Class<?> pojoClass, String title, String fieldNames) {
        HttpServletResponse response = WebHelper.getResponse();
        if(response != null) {
            exportWeb(response, data, pojoClass, title, null, fieldNames);
        }
    }

    /**
     * Web导出Excel
     * @param response http响应对象
     * @param data 导出的数据
     * @param pojoClass 实体对象类型
     * @param title 标题
     * @param fieldNames 导出字段名称字符串,逗号隔开(@Excel注解中的name属性)
     */
    public static void exportWeb(HttpServletResponse response, @NotNull List data, Class<?> pojoClass, String title,
            ExportParams exportParams, String fieldNames) {
        if(exportParams == null) {
            exportParams = new ExportParams(title, title, ExcelType.XSSF);
        }

        Workbook workbook = new SXSSFWorkbook();
        createSheet(workbook, exportParams, pojoClass, data, fieldNames);
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.setHeader("Content-Type", "application/octet-stream;charset=utf-8");
        try {
            response.setHeader("Content-Disposition",
                               "attachment;filename=" + URLEncoder.encode(title + ".xlsx", "UTF-8"));
        } catch(UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", "0");
        response.setHeader("Set-Cookie", "fileDownload=true; path=/");

        try {
            workbook.write(response.getOutputStream());
            workbook.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取实体对象Excel导出字段列表
     * @param pojoClass 实体类型
     */
    public static List<String> getExcelFiledNames(Class<?> pojoClass) {
        List<ExcelExportEntity> excelParams = new ArrayList<>();
        //得到所有字段
        Field[] fileds = PoiPublicUtil.getClassFields(pojoClass);
        ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
        String targetId = etarget == null ? null : etarget.value();
        try {
            new ExcelExportService().getAllExcelField(null, targetId, fileds, excelParams, pojoClass, null, null);
            return excelParams.stream().map(ExcelBaseEntity::getName).collect(Collectors.toList());
        } catch(Exception e) {
            e.printStackTrace();
        }
        return Lists.newArrayList();
    }

    private static void createSheet(Workbook workbook, ExportParams entity, Class<?> pojoClass, Collection<?> dataSet,
            String fieldNames) {
        if(workbook == null || entity == null || pojoClass == null || dataSet == null) {
            throw new ExcelExportException(ExcelExportEnum.PARAMETER_ERROR);
        }
        try {
            List<ExcelExportEntity> excelParams = new ArrayList<>();
            // 得到所有字段
            Field[] fileds = PoiPublicUtil.getClassFields(pojoClass);
            ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
            String targetId = etarget == null ? null : etarget.value();
            ExcelExportService excelExportService = new ExcelExportService();
            excelExportService.getAllExcelField(entity.getExclusions(), targetId, fileds, excelParams, pojoClass, null,
                                                null);
            final List<ExcelExportEntity> exportList;
            if(Helper.isNotBlank(fieldNames)) {
                exportList = new ArrayList<>();
                String[] fieldNameList = Helper.splitToArray(fieldNames);
                for(String item : fieldNameList) {
                    excelParams.stream().filter(p -> p.getName().equals(item)).findFirst().ifPresent(exportList::add);
                }
            }
            else {
                exportList = excelParams;
            }
            //获取所有参数后,后面的逻辑判断就一致了
            excelExportService.createSheetForMap(workbook, entity, exportList, dataSet);
        } catch(Exception e) {
            throw new ExcelExportException(ExcelExportEnum.EXPORT_ERROR, e.getCause());
        }
    }

   /**
    * 获取excel字段/字段注释Map
    *
    * @param pojoClass 实体对象类型
    */
   public static Map<String, String> getExcelFieldMap(@NotNull Class<?> pojoClass) {
       Map<String, String> map = new HashMap<>();
       ExcelTarget etarget = pojoClass.getAnnotation(ExcelTarget.class);
       String targetId = etarget == null ? null : etarget.value();
       Field[] fields;
       do {
           fields = pojoClass.getDeclaredFields();
           for (int i = 0; i < fields.length; i++) {
               Field field = fields[i];
               String fieldName = field.getName();
               String fieldComment = fieldName;
               if (field.getAnnotation(Excel.class) != null) {
                   Excel excel = field.getAnnotation(Excel.class);
                   fieldComment = PoiPublicUtil.getValueByTargetId(excel.name(), targetId, null);
                   if (StringUtils.isBlank(fieldComment)) {
                       fieldComment = fieldName;
                   }
               }
               map.put(fieldName, fieldComment);
           }
           pojoClass = pojoClass.getSuperclass();
       } while (pojoClass != Object.class && pojoClass != null);
       return map;
   }

    // /**
    //  * 自适应excel单元格
    //  *
    //  * @param sheet excel
    //  */
    // public static void autoSizeExcelColumn(Sheet sheet) {
    //     for (int columnNum = 0; columnNum <= 8; columnNum++) {
    //         int columnWidth = sheet.getColumnWidth(columnNum) / 256;
    //         for (int rowNum = 0; rowNum < sheet.getLastRowNum(); rowNum++) {
    //             Row currentRow;
    //             //当前行未被使用过
    //             if (sheet.getRow(rowNum) == null) {
    //                 currentRow = sheet.createRow(rowNum);
    //             } else {
    //                 currentRow = sheet.getRow(rowNum);
    //             }
    //             if (currentRow.getCell(columnNum) != null) {
    //                 Cell currentCell = currentRow.getCell(columnNum);
    //                 if (currentCell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
    //                     int length = currentCell.getStringCellValue().getBytes().length;
    //                     if (columnWidth < length) {
    //                         columnWidth = length;
    //                     }
    //                 }
    //             }
    //         }
    //         sheet.setColumnWidth(columnNum, columnWidth * 256);
    //     }
    // }
}
